#include "stdafx.h"
#include "ClientServiceRequester.h"
#include "..\Common\CommonUtil.h"
#include "ClientThreads.h"
#include <atlstr.h>

service_requester::service_requester(void)
: m_pClient(NULL), m_pObjectManager(NULL), m_ServiceNetwork(NULL), m_pCommander(NULL) {
	InitializeCriticalSection(&m_CriticalSection);
}

service_requester::~service_requester(void) {
	if(m_ServiceNetwork) {
		delete m_ServiceNetwork;
		m_ServiceNetwork = NULL;
	}
	DeleteCriticalSection(&m_CriticalSection);
}

void service_requester::LinkClient(client_base* pClient) {
	assert(m_pClient == NULL);
	assert(pClient != NULL);

	m_pClient = pClient;
}

void service_requester::LinkObjectManager(object_manager* pObjectManager) {
	assert(m_pObjectManager == NULL);
	assert(pObjectManager != NULL);

	m_pObjectManager = pObjectManager;
}

void service_requester::LinkCommander(hz::commander* pCommander) {
	assert(m_pCommander == NULL);
	assert(pCommander != NULL);

	m_pCommander = pCommander;
}

void service_requester::SetServiceNetwork(network*	ServiceNetwork) {
	assert(m_ServiceNetwork == NULL);
	assert(ServiceNetwork != NULL);

	this->m_ServiceNetwork = ServiceNetwork;
}


bool service_requester::RequestByString(wstring String) {
	m_pClient->Focus();

	if(String[0] != '/')	// order starting character is /
		return false;	
	
	wchar_t* Order = wcstok(&(String[0]), _T(" "));

	if(wcscmp(Order, ORDER_STRING_CLIENTS) == 0) {
		// output Clients string .
		object_manager::client_info_list ClientList;
		ClientList = m_pObjectManager->GetClientList();	// copy client list. 

		// print all client list.
		int ClientIndex = 0;
		for(object_manager::client_info_list::iterator it = ClientList.begin();
			it != ClientList.end();
			++it) {
				CString IPString(inet_ntoa(it->IP));
				m_pCommander->Out(_T("[System] Other client Info[%d] ClientCode[%d]/IP[%s]/UdpPort[%d]"),
					++ClientIndex, it->ClientCode, IPString, it->UdpPort);
		}
		return true;
	}

	if(wcscmp(Order, ORDER_STRING_MY_CLIENTCODE) == 0) {
		// output this client code.  		
		m_pCommander->Out(_T("[System] Client Code : %d"), m_pClient->GetClientCode());
		return true;
	}

	if(wcscmp(Order, ORDER_STRING_TOGGLE_MY_SEND_COUNT) == 0) {
		if(m_pObjectManager->SwitchShowMySendSyncDataCount())
			m_pCommander->Out(_T("[System] Show my sync data count"));
		else
			m_pCommander->Out(_T("[System] Hide my sync data count"));

		return true;
	}

	if(wcscmp(Order, ORDER_STRING_TOGGLE_RECV_COUNT) == 0) {
		if(m_pObjectManager->SwitchShowRecvSyncDataCount())
			m_pCommander->Out(_T("[System] Show other sync data counter"));
		else
			m_pCommander->Out(_T("[System] Hied other sync data counter"));

		return true;
	}

	if(wcscmp(Order, ORDER_STRING_TOGGLE_EFFECTIVE_RECV_COUNT) == 0) {
		if(m_pObjectManager->SwitchShowEffectiveRecvSyncDataCount())
			m_pCommander->Out(_T("[System] Effective recv data count"));
		else
			m_pCommander->Out(_T("[System] All recving data count"));

		return true;
	}

	if(wcscmp(Order, ORDER_STRING_TOGGLE_POSITION_INTERPOLATION) == 0) {
		if(m_pObjectManager->SwitchPosInterpolation())
			m_pCommander->Out(_T("[System] On object position interpolation "));
		else
			m_pCommander->Out(_T("[System] off object position interpolation "));
		return true;
	}

	if(wcscmp(Order, ORDER_STRING_CLEAR_COMMANDER) == 0) {
		m_pCommander->Clear();
		return true;
	}

	if(wcscmp(Order, ORDER_STRING_MONITER_BROADCAST) == 0) {		
		if(m_pClient->SwitchMoniterBroadcaster())
			m_pCommander->Out(_T("[System] On Moniter Broadcaster "));
		else
			m_pCommander->Out(_T("[System] Off Moniter Broadcaster "));
		return true;
	}	

	if(wcscmp(Order, ORDER_STRING_FRAME30) == 0) {		
		m_pClient->SetBorderFrameTime(0.03333333);
		m_pCommander->Out(_T("[System] Set border frame(30)."));		
		return true;
	}	

	if(wcscmp(Order, ORDER_STRING_FRAME15) == 0) {		
		m_pClient->SetBorderFrameTime(0.06666666);
		m_pCommander->Out(_T("[System] Set border frame(15)."));		
		return true;
	}	

	if(wcscmp(Order, ORDER_STRING_FRAME10) == 0) {		
		m_pClient->SetBorderFrameTime(0.10000000);
		m_pCommander->Out(_T("[System] Set border frame(10)."));		
		return true;
	}	
	if(wcscmp(Order, ORDER_STRING_FRAME3) == 0) {		
		m_pClient->SetBorderFrameTime(0.3333333);
		m_pCommander->Out(_T("[System] Set border frame(3)."));		
		return true;
	}	

	if(wcscmp(Order, ORDER_STRING_UDP_LINK_COUNT) == 0) {	
		object_manager::client_info_list ClientList;
		ClientList = m_pObjectManager->GetClientList(); // copy client list. 

		int ClientIndex = 0;
		object_manager::client_info_list::iterator it = ClientList.begin();
		++it; // 0 is server
		for(;
			it != ClientList.end();
			++it) {				
				m_pCommander->Out(_T("[System] Client[%d] Udp Link Try Count[%d]"),
					it->ClientCode, it->UdpLinkCount);
		}
		
		return true;
	}	

	// add point. Request string. (user request)

	m_pCommander->Out(_T("[System] Wrong order"));

	return true;
}

bool service_requester::RequestByCode(SERVICE_MESSAGE RequestCode) {
	switch(RequestCode) {
		case S_REQUEST_CODE:
			return RequestREQUEST_CODE();
			break;

		case S_REQUEST_CLIENT:
			return RequestREQUEST_CLIENT();
			break;

		case S_REQUEST_OBJECT:
			return RequestREQUEST_OBJECT();
			break;

		case S_NOTICE_ACCESS_OFF:			
			return RequestNOTICE_ACCESS_OFF();
			break;

		case S_REQUEST_RELAY_LINK:
			return RequestREQUEST_RELAY_LINK();
			break;

		default:
			assert(_T("ErrorLine"));
			return false;
	}
	return false;
}

bool service_requester::RequestREQUEST_CODE(void) {
	cs_auto cs(&m_CriticalSection);

	bool Result = false;

	SERVICE_MESSAGE MsgType = S_REQUEST_CODE;
	service_msg_REQUEST_CODE Msg;
	
	Result = m_ServiceNetwork->Send((char*)&MsgType, sizeof(MsgType));	
	Result = m_ServiceNetwork->Send((char*)&Msg, sizeof(Msg));



	int RecvLen;
	service_msg_REQUEST_CODE_RETURN RecvData;
	Result = m_ServiceNetwork->Recv((char*)&MsgType, sizeof(MsgType), &RecvLen);
	assert(sizeof(MsgType) == RecvLen);
	assert(MsgType == SR_REQUEST_CODE);
	Result = m_ServiceNetwork->Recv((char*)&RecvData, sizeof(RecvData), &RecvLen);
	assert(sizeof(RecvData) == RecvLen);

	m_pClient->SetClientCode(RecvData.ClientCode);	

	ip ServerIP;
	ServerIP.s_addr = inet_addr(m_pClient->GetServerIP().c_str());
	// Register Server Port to UDP Network .
	m_pObjectManager->AddClient(ServerIP, 0, m_pClient->GetServerUdpPort());

	return true;	
}

bool service_requester::RequestREQUEST_CLIENT(void) 
{
	cs_auto cs(&m_CriticalSection);

	SERVICE_MESSAGE MsgType = S_REQUEST_CLIENT;
	service_msg_REQUEST_CLIENT Msg;
	
	m_ServiceNetwork->Send((char*) &MsgType, sizeof(MsgType));	
	m_ServiceNetwork->Send((char*) &Msg, sizeof(Msg));



	int RecvLen;	
	service_msg_REQUEST_CLIENT_RETURN RecvData;
	m_ServiceNetwork->Recv((char*) &MsgType, sizeof(MsgType), &RecvLen);
	m_ServiceNetwork->Recv((char*) &RecvData, sizeof(RecvData), &RecvLen);

	RecvData.ExtraData = new service_msg_REQUEST_CLIENT_RETURN::client_info[RecvData.ClientNumber];

	m_ServiceNetwork->Recv((char*) RecvData.ExtraData, sizeof(service_msg_REQUEST_CLIENT_RETURN) * RecvData.ClientNumber, &RecvLen);

	for(int i = 0; i < RecvData.ClientNumber; i++)
		m_pObjectManager->AddClient(RecvData.ExtraData[i].IP, RecvData.ExtraData[i].ClientCode, RecvData.ExtraData[i].UdpPort);

	delete[] RecvData.ExtraData;

	return true;
}

bool service_requester::RequestREQUEST_OBJECT(void) 
{
	cs_auto cs(&m_CriticalSection);

	SERVICE_MESSAGE MsgType = S_REQUEST_OBJECT;
	service_msg_REQUEST_OBJECT Msg;
	
	m_ServiceNetwork->Send((char*) &MsgType, sizeof(MsgType));	
	m_ServiceNetwork->Send((char*) &Msg, sizeof(Msg));



	int RecvLen;	
	service_msg_REQUEST_OBJECT_RETURN RecvData;
	m_ServiceNetwork->Recv((char*)&MsgType, sizeof(MsgType), &RecvLen);
	m_ServiceNetwork->Recv((char*)&RecvData, sizeof(RecvData), &RecvLen);

	RecvData.ExtraData = new service_msg_REQUEST_OBJECT_RETURN::object_info[RecvData.ObjectNumber];

	m_ServiceNetwork->Recv((char *) RecvData.ExtraData, sizeof(service_msg_REQUEST_OBJECT_RETURN::object_info) * RecvData.ObjectNumber, &RecvLen);

	for(int i = 0; i < RecvData.ObjectNumber; i++)
		m_pObjectManager->AddObject(RecvData.ExtraData[i].ObjectID, 
									RecvData.ExtraData[i].ObjectType, 
									RecvData.ExtraData[i].OwnerCode,
									RecvData.ExtraData[i].ObjectExtraLength, 
									(char*) &(RecvData.ExtraData[i].ObjectExtra));
	delete[] RecvData.ExtraData;

		return true;
}

bool service_requester::RequestREQUEST_RELAY_LINK(void) {
	cs_auto cs(&m_CriticalSection);

	int Result = false;

	udp_link_thread_arg* Arg = new udp_link_thread_arg;
	Arg->TargetIP			= m_pClient->GetServerIP();
	Arg->TargetPort			= m_pClient->GetServerUdpPort();
	Arg->PtrUDPNetwork		= m_pClient->GetUDPNetwork();
	Arg->MyClientCode		= m_pClient->GetClientCode();
	int LinkThreadNumber	= m_pClient->ThreadManager().CreateNewThread(UdpLinkThread, Arg);
	Sleep(2500);			// udp link time.

	SERVICE_MESSAGE MsgType = S_REQUEST_RELAY_LINK;
	service_msg_REQUEST_OBJECT Msg;

	Result = m_ServiceNetwork->Send((char*)&MsgType, sizeof(MsgType));
	Result = m_ServiceNetwork->Send((char*)&Msg, sizeof(Msg));



	int RecvLen;
	service_msg_REQUEST_RELAY_LINK_RETURN RecvData;
	Result = m_ServiceNetwork->Recv((char*)&MsgType, sizeof(MsgType), &RecvLen);
	assert(sizeof(MsgType) == RecvLen);
		
	Result = m_ServiceNetwork->Recv((char*)&RecvData, sizeof(RecvData), &RecvLen);
	assert(sizeof(RecvData) == RecvLen);

	m_pClient->ThreadManager().WaitThread(LinkThreadNumber);

	if(RecvData.Result) {		
		return true;
	}
	else
		return false;
}

bool service_requester::RequestNOTICE_NEW_OBJECT(OBJECT_TYPE ObjectType, int ExtraLength, char* Extra) {
	cs_auto cs(&m_CriticalSection);

	bool Result = false;

	SERVICE_MESSAGE MsgType = S_NOTICE_NEW_OBJECT;
	service_msg_NOTICE_NEW_OBJECT SendData;
	SendData.ObjectType = ObjectType;
	SendData.OwnerCode = m_pClient->GetClientCode();
	SendData.ExtraLength = ExtraLength;
	SendData.ExtraPtr = NULL;		// send by Extra.

	Result = m_ServiceNetwork->Send((char*)&MsgType, sizeof(MsgType));
	Result = m_ServiceNetwork->Send((char*)&SendData, sizeof(SendData));
	Result = m_ServiceNetwork->Send(Extra, ExtraLength);

	// not use recv. for fast process. 
	/*int RealLen = NULL;
	service_msg_NOTICE_NEW_OBJECT_RETURN RecvData;
	Result = m_ServiceNetwork->Recv((char*)&MsgType, sizeof(MsgType), &RealLen);
	assert( sizeof(MsgType) == RealLen);
	assert(MsgType == SR_NOTICE_NEW_OBJECT);
	Result = m_ServiceNetwork->Recv((char*)&RecvData, sizeof(RecvData), &RealLen);
	assert( sizeof(RecvData) == RealLen);*/

	return true;
}

bool service_requester::RequestNOTICE_DEL_OBJECT(unsigned int ObjectID) {
 	cs_auto cs(&m_CriticalSection);

	bool Result = false;
	SERVICE_MESSAGE MsgType = S_NOTICE_DEL_OBJECT;
	service_msg_NOTICE_DEL_OBJECT SendData;
	SendData.ObjectID = ObjectID;
	Result = m_ServiceNetwork->Send((char*)&MsgType, sizeof(MsgType));
	Result = m_ServiceNetwork->Send((char*)&SendData, sizeof(SendData));

	/*int RecvLen;
	service_msg_NOTICE_DEL_OBJECT_RETURN RecvData;
	Result = m_ServiceNetwork->Recv((char*)&MsgType, sizeof(MsgType), &RecvLen);
	assert( sizeof(MsgType) == RecvLen);
	assert(MsgType == SR_NOTICE_DEL_OBJECT);
	Result = m_ServiceNetwork->Recv((char*)&RecvData, sizeof(RecvData), &RecvLen);
	assert( sizeof(RecvData) == RecvLen);*/ 

	return true;
}

bool service_requester::RequestNOTICE_ACCESS_OFF(void) {
	cs_auto cs(&m_CriticalSection);

	bool Result = false;
	SERVICE_MESSAGE MsgType = S_NOTICE_ACCESS_OFF; 
	service_msg_NOTICE_ACCESS_OFF SendData;
	SendData.ClientID = m_pClient->GetClientCode();

	Result = m_ServiceNetwork->Send((char*) &MsgType, sizeof(MsgType));
	Result = m_ServiceNetwork->Send((char*) &SendData, sizeof(SendData));

	/*int RealLen = NULL;
	service_msg_NOTICE_ACCESS_OFF RecvData;
	Result = m_ServiceNetwork->Recv((char*) &MsgType, sizeof(MsgType), &Reallen);
	Result = m_ServiceNetwork->Recv((char*) &RecvData, sizeof(RecvData), &RealLen);*/

	return true;
}

bool service_requester::RequestNOTICE_MISSILE_CRUSH(unsigned int MissileID, unsigned int TargetID) {
	cs_auto cs(&m_CriticalSection);

	bool Result = false;
	SERVICE_MESSAGE MsgType = S_NOTICE_MISSILE_CRUSH; 
	service_msg_NOTICE_MISSILE_CRUSH SendData;
	SendData.MissileOwner	= m_pClient->GetClientCode();
	SendData.MissileId		= MissileID;
	SendData.TargetClient	= TargetID;

	Result = m_ServiceNetwork->Send((char*) &MsgType, sizeof(MsgType));
	Result = m_ServiceNetwork->Send((char*) &SendData, sizeof(SendData));

	/*int RecvLen;
	service_msg_NOTICE_MISSILE_CRUSH_RETURN RecvData;
	Result = m_ServiceNetwork->Recv((char*)&MsgType, sizeof(MsgType), &RecvLen);
	assert( sizeof(MsgType) == RecvLen);
	assert(MsgType == SR_NOTICE_MISSILE_CRUSH);
	Result = m_ServiceNetwork->Recv((char*)&RecvData, sizeof(RecvData), &RecvLen);
	assert( sizeof(RecvData) == RecvLen);*/ 

	return true;
}

bool service_requester::RequestNOTICE_MESSAGE(wstring String)
{
	wchar_t SendString[128];
	wsprintf(SendString,_T("Client Code %d : %s"),m_pClient->GetClientCode(), String.c_str());

	SERVICE_MESSAGE MsgType = S_NOTICE_MESSAGE;
	service_msg_NOTICE_MESSAGE Msg;

	Msg.MsgString = (char*)SendString;
	Msg.MsgLength = wcslen(SendString) * 2 + 2;
	
	m_ServiceNetwork->Send((char *) &MsgType, sizeof(MsgType));
	m_ServiceNetwork->Send((char *) &Msg, sizeof(Msg));
	m_ServiceNetwork->Send((char *) Msg.MsgString, Msg.MsgLength);

	return true;
}